#ifndef _MAT_DEF_H_
#define _MAT_DEF_H_

#include "./../../stl_util/stl_util.h"
#include "./../../mathematics/mathematics.h"

namespace Mathematics {

	//! Allows the use of matrices.
	/*!
		Classes for using 1 and 2 Dimensional matrices with most of
		functions are using operators. Data insetion and manipulations
		are easier this way. Get used to it!
	*/
	namespace Matrix {

		using namespace Define;
		using namespace Debug;
		using namespace Except;
		using namespace Holders;
		
		/*! Type declaration for matrix' actions */
		typedef enum {
			/*! Skip the present value */
			pr, 
			/*! Goes for next Matrix line */
			nl
		} MatrixManipulation;
		
		string& operator += ( string &str, const MatrixManipulation &obj );

		inline string operator + (const string &str, const MatrixManipulation &obj) {
			string result = str;
			return result += obj;
		};

		inline string operator + (const MatrixManipulation &obj, const string &str) {
			return string("") + obj + str;
		};

		//	ostream handling
		/*! 
			ostream printing
			
			\param file ostream where the log should be printed
			\param obj the object to be printed
			\return modified ostream
			
			\code
			cout << pr << endl; // prints the value of the manipulation
			\endcode
		*/
		inline ostream& operator << (ostream &file, const MatrixManipulation &obj) {
			return file << string("") + obj;
		};
		
		template< class TypeA, class TypeB >
			class IncompatibleParametersException: public Exception {
			protected:
				TypeA obj_left;
				TypeB obj_right;
			public:
				IncompatibleParametersException( const string &message, const TypeA &left, const TypeB &right, Exception *innerException = NULL ):
					Exception( message, innerException ), obj_left(left), obj_right(right) {
				};
				~IncompatibleParametersException() {
				};

				inline TypeA getLeft() const {
					return obj_left;
				};
				inline TypeB getRight() const {
					return obj_right;
				};

				// --- Writeable ---
				virtual bool filePrint( FILE *parq = stdin ) const {
					return false;
				};

				inline virtual string toS() const {
					return Exception::toS() + "\nLeft: " + obj_left + "\nRight: " + obj_right;
				};

				// --- Classificable ---
				static inline string ClassName() {
					return "IncompatibleParametersException";
				};

				inline virtual string className() const {
					return ClassName();
				};

			};

	};
};

#endif
